'use client';

import { mqttService } from './mqttService';
import { DroneLocationData, MqttConfig, MqttConnectionStatus } from './types';

// 无人机数据变更回调类型
type DroneDataChangeCallback = (data: Record<string, DroneLocationData>) => void;

/**
 * 无人机位置数据服务类
 * 处理MQTT接收到的无人机位置数据
 */
class DroneLocationService {
  private connectionStatus: MqttConnectionStatus = MqttConnectionStatus.DISCONNECTED;
  private droneLocations: Record<string, DroneLocationData> = {};
  private droneChangeCallbacks: DroneDataChangeCallback[] = [];
  private statusChangeCallbacks: ((status: MqttConnectionStatus) => void)[] = [];
  
  // 无人机位置消息主题
  private readonly DRONE_LOCATION_TOPIC = 'dji/aircraft/location';
  
  /**
   * 获取MQTT配置，优先从环境变量读取
   * @returns MQTT配置对象
   */
  private getConfig(): MqttConfig {
    // 在客户端环境中，使用带有'NEXT_PUBLIC_'前缀的环境变量
    const getEnv = (key: string, defaultValue: string): string => {
      if (typeof window !== 'undefined') {
        // 客户端环境
        return (window as Window & typeof globalThis & { __ENV__?: Record<string, string> }).__ENV__?.[key] || 
               process.env[`NEXT_PUBLIC_${key}`] || 
               defaultValue;
      }
      // 服务器环境
      return process.env[key] || defaultValue;
    };
    
    return {
      host: getEnv('MQTT_HOST', '113.45.136.1'),
      port: parseInt(getEnv('MQTT_PORT', '8083')),
      protocol: getEnv('MQTT_PROTOCOL', 'ws') as 'ws' | 'wss' | 'mqtt' | 'mqtts',
      username: getEnv('MQTT_USERNAME', 'admin'),
      password: getEnv('MQTT_PASSWORD', 'admin123'),
      clientId: `dashboard_${Date.now()}_${Math.random().toString(16).slice(2, 8)}`,
    };
  }
  
  /**
   * 初始化MQTT服务并连接
   */
  public initialize(): void {
    console.log('初始化无人机位置数据服务');
    
    // 如果已经连接，则只需确保订阅了相关主题
    if (mqttService.isConnected()) {
      console.log('MQTT服务已连接，确保订阅无人机位置主题');
      this.subscribeToDroneLocation();
      return;
    }
    
    // 从环境变量获取配置
    const config = this.getConfig();
    console.log('MQTT配置:', { 
      host: config.host, 
      port: config.port, 
      protocol: config.protocol,
      username: config.username,
      // 出于安全考虑，不打印密码
    });
    
    // 初始化MQTT配置
    mqttService.initialize(config);
    
    // 注册状态变更回调
    mqttService.onStatusChange(this.handleStatusChange.bind(this));
    
    // 连接到MQTT服务器
    mqttService.connect();
  }

  /**
   * 监听无人机位置数据变更
   * @param callback 数据变更回调函数
   */
  public onDroneDataChange(callback: DroneDataChangeCallback): void {
    if (!this.droneChangeCallbacks.includes(callback)) {
      this.droneChangeCallbacks.push(callback);
      
      // 如果已经有数据，立即调用回调
      if (Object.keys(this.droneLocations).length > 0) {
        try {
          callback({ ...this.droneLocations });
        } catch (error) {
          console.error('执行无人机数据变更回调时出错:', error);
        }
      }
    }
  }

  /**
   * 移除无人机位置数据变更监听
   * @param callback 数据变更回调函数
   */
  public offDroneDataChange(callback: DroneDataChangeCallback): void {
    const index = this.droneChangeCallbacks.indexOf(callback);
    if (index !== -1) {
      this.droneChangeCallbacks.splice(index, 1);
    }
  }
  
  /**
   * 监听连接状态变更
   * @param callback 状态变更回调函数
   */
  public onConnectionStatusChange(callback: (status: MqttConnectionStatus) => void): void {
    if (!this.statusChangeCallbacks.includes(callback)) {
      this.statusChangeCallbacks.push(callback);
      
      // 立即通知当前状态
      try {
        callback(this.connectionStatus);
      } catch (error) {
        console.error('执行状态变更回调时出错:', error);
      }
    }
  }
  
  /**
   * 移除连接状态变更监听
   * @param callback 状态变更回调函数
   */
  public offConnectionStatusChange(callback: (status: MqttConnectionStatus) => void): void {
    const index = this.statusChangeCallbacks.indexOf(callback);
    if (index !== -1) {
      this.statusChangeCallbacks.splice(index, 1);
    }
  }

  /**
   * 获取所有无人机位置数据
   */
  public getAllDroneLocations(): Record<string, DroneLocationData> {
    return { ...this.droneLocations };
  }

  /**
   * 获取指定无人机的位置数据
   * @param droneId 无人机ID
   */
  public getDroneLocation(droneId: string): DroneLocationData | null {
    return this.droneLocations[droneId] || null;
  }

  /**
   * 获取当前连接状态
   */
  public getConnectionStatus(): MqttConnectionStatus {
    return this.connectionStatus;
  }
  
  /**
   * 检查是否已连接
   */
  public isConnected(): boolean {
    return this.connectionStatus === MqttConnectionStatus.CONNECTED;
  }

  /**
   * 手动重新连接MQTT服务
   */
  public reconnect(): void {
    mqttService.disconnect();
    mqttService.connect();
  }

  /**
   * 断开MQTT连接
   */
  public disconnect(): void {
    mqttService.disconnect();
  }
  
  /**
   * 处理MQTT状态变更
   */
  private handleStatusChange(status: MqttConnectionStatus): void {
    console.log(`MQTT连接状态变更: ${status}`);
    this.connectionStatus = status;
    
    // 如果已连接，订阅无人机位置主题
    if (status === MqttConnectionStatus.CONNECTED) {
      this.subscribeToDroneLocation();
    }
    
    // 通知所有状态变更回调
    this.statusChangeCallbacks.forEach(callback => {
      try {
        callback(status);
      } catch (error) {
        console.error('执行状态变更回调时出错:', error);
      }
    });
  }
  
  /**
   * 订阅无人机位置主题
   */
  private subscribeToDroneLocation(): void {
    // 检查是否已经订阅了该主题
    if (mqttService.isTopicSubscribed(this.DRONE_LOCATION_TOPIC)) {
      console.log(`无人机位置主题已订阅: ${this.DRONE_LOCATION_TOPIC}`);
      return;
    }
    
    console.log(`订阅无人机位置主题: ${this.DRONE_LOCATION_TOPIC}`);
    
    mqttService.subscribe(
      { topic: this.DRONE_LOCATION_TOPIC, qos: 0 },
      this.handleDroneLocationMessage.bind(this)
    );
  }
  
  /**
   * 处理无人机位置消息
   */
  private handleDroneLocationMessage(topic: string, message: Buffer): void {
    try {
      // 解析JSON消息
      const payload = message.toString();
      const data = JSON.parse(payload) as DroneLocationData;
      
      // 检查必要字段
      if (!data.drone_id || !data.gui_id) {
        console.warn('收到的无人机位置数据缺少必要字段:', data);
        return;
      }
      
      // 更新数据存储
      this.droneLocations[data.drone_id] = data;
      
      // 通知所有回调
      this.notifyDroneDataChange();
      
    } catch (error) {
      console.error('处理无人机位置消息时出错:', error, message.toString());
    }
  }
  
  /**
   * 通知所有无人机数据变更回调
   */
  private notifyDroneDataChange(): void {
    const data = { ...this.droneLocations };
    
    this.droneChangeCallbacks.forEach(callback => {
      try {
        callback(data);
      } catch (error) {
        console.error('执行无人机数据变更回调时出错:', error);
      }
    });
  }
}

// 导出单例实例
export const droneLocationService = new DroneLocationService(); 